#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <getopt.h>
#include <sys/socket.h>
#include <linux/socket.h>
#include <linux/if_alg.h>

#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif

struct crypt_cipher {
    int tfmfd;
    int opfd;
};

struct crypt_method {
    char *type;
    char *mode;
    char *plain_buf;
    char *encrypt_buf;
    char *key_buf;
    char *iv_buf;
    int key_len;
    int iv_len;
    int text_len;
};

int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
{
    *tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
    if (*tfmfd == -1)
        return -ENOTSUP;

    if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) {
        close(*tfmfd);
        *tfmfd = -1;
        return -ENOENT;
    }

    *opfd = accept(*tfmfd, NULL, 0);
    if (*opfd == -1) {
        close(*tfmfd);
        *tfmfd = -1;
        return -EINVAL;
    }

    return 0;
}

int crypt_cipher_destroy(struct crypt_cipher *ctx)
{
    if (ctx->tfmfd != -1)
        close(ctx->tfmfd);
    if (ctx->opfd != -1)
        close(ctx->opfd);
    memset(ctx, 0, sizeof(*ctx));
    free(ctx);
    return 0;
}

/*
 *ciphers
 *
 * ENOENT - algorithm not available
 * ENOTSUP - AF_ALG family not available
 * (but cannot check specificaly for skcipher API)
 */
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
            const char *mode, const void *key_buf, size_t length)
{
    struct crypt_cipher *h;
    struct sockaddr_alg sa = {
        .salg_family = AF_ALG,
        .salg_type = "skcipher",
    };
    int r;

    h = malloc(sizeof(*h));
    if (!h)
        return -ENOMEM;

    snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
        "%s(%s)", mode, name);

    r = crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd);
    if (r < 0) {
        free(h);
        return r;
    }

    if (length && strcmp(name, "cipher_null") &&
        setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, key_buf, length) == -1) {
        crypt_cipher_destroy(h);
        return -EINVAL;
    }

    *ctx = h;
    return 0;
}

/* The in/out should be aligned to page boundary */
static int crypt_cipher_crypt(struct crypt_cipher *ctx,
            const char *in, char *out, size_t length,
            const char *iv, size_t iv_length,
            unsigned int direction)
{
    int r = 0;
    ssize_t len;
    struct af_alg_iv *alg_iv;
    struct cmsghdr *header;
    unsigned int *type;
    struct iovec iov = {
        .iov_base = (void*)(unsigned int *)in,
        .iov_len = length,
    };
    int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0;
    char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
    struct msghdr msg = {
        .msg_control = buffer,
        .msg_controllen = sizeof(buffer),
        .msg_iov = &iov,
        .msg_iovlen = 1,
    };

    if (!in || !out || !length)
        return -EINVAL;

    if ((!iv && iv_length) || (iv && !iv_length))
        return -EINVAL;

    memset(buffer, 0, sizeof(buffer));

    /* Set encrypt/decrypt operation */
    header = CMSG_FIRSTHDR(&msg);
    if (!header)
        return -EINVAL;

    header->cmsg_level = SOL_ALG;
    header->cmsg_type = ALG_SET_OP;
    header->cmsg_len = CMSG_LEN(sizeof(*type));
    type = (void*)CMSG_DATA(header);
    *type = direction;

    /* Set IV */
    if (iv) {
        header = CMSG_NXTHDR(&msg, header);
        header->cmsg_level = SOL_ALG;
        header->cmsg_type = ALG_SET_IV;
        header->cmsg_len = iv_msg_size;
        alg_iv = (void*)CMSG_DATA(header);
        alg_iv->ivlen = iv_length;
        memcpy(alg_iv->iv, iv, iv_length);
    }

    len = sendmsg(ctx->opfd, &msg, 0);
    if (len != (ssize_t)length) {
        r = -EIO;
        goto bad;
    }

    len = read(ctx->opfd, out, length);
    if (len != (ssize_t)length)
        r = -EIO;
bad:
    return r;
}

int crypt_cipher_encrypt(struct crypt_cipher *ctx,
            const char *in, char *out, size_t length,
            const char *iv, size_t iv_length)
{
    return crypt_cipher_crypt(ctx, in, out, length,
        iv, iv_length, ALG_OP_ENCRYPT);
}

int crypt_cipher_decrypt(struct crypt_cipher *ctx,
            const char *in, char *out, size_t length,
            const char *iv, size_t iv_length)
{
    return crypt_cipher_crypt(ctx, in, out, length,
            iv, iv_length, ALG_OP_DECRYPT);
}

static const unsigned char plain_text[] = {
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
    0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
    0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
    0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
};

/* ================ aes cbc 128===================== */
static const unsigned char aes_cbc_128_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_cbc_128_key_buf[] = {
    0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
};

static const unsigned char aes_cbc_128_encrypt_text[] = {

    0x76,0x49,0xab,0xac, 0x81,0x19,0xb2,0x46, 0xce,0xe9,0x8e,0x9b, 0x12,0xe9,0x19,0x7d,
    0x50,0x86,0xcb,0x9b, 0x50,0x72,0x19,0xee, 0x95,0xdb,0x11,0x3a, 0x91,0x76,0x78,0xb2,
    0x73,0xbe,0xd6,0xb8, 0xe3,0xc1,0x74,0x3b, 0x71,0x16,0xe6,0x9e, 0x22,0x22,0x95,0x16,
    0x3f,0xf1,0xca,0xa1, 0x68,0x1f,0xac,0x09, 0x12,0x0e,0xca,0x30, 0x75,0x86,0xe1,0xa7,

};

/* ================ aes cbc 192===================== */
static const unsigned char aes_cbc_192_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_cbc_192_key_buf[] = {
    0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
    0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
};

static const unsigned char aes_cbc_192_encrypt_text[] = {
    0x4f,0x02,0x1d,0xb2, 0x43,0xbc,0x63,0x3d, 0x71,0x78,0x18,0x3a, 0x9f,0xa0,0x71,0xe8,
    0xb4,0xd9,0xad,0xa9, 0xad,0x7d,0xed,0xf4, 0xe5,0xe7,0x38,0x76, 0x3f,0x69,0x14,0x5a,
    0x57,0x1b,0x24,0x20, 0x12,0xfb,0x7a,0xe0, 0x7f,0xa9,0xba,0xac, 0x3d,0xf1,0x02,0xe0,
    0x08,0xb0,0xe2,0x79, 0x88,0x59,0x88,0x81, 0xd9,0x20,0xa9,0xe6, 0x4f,0x56,0x15,0xcd,
};

/* ================ aes cbc 256===================== */
static const unsigned char aes_cbc_256_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_cbc_256_key_buf[] = {
    0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
    0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
};

static const unsigned char aes_cbc_256_encrypt_text[] = {
    0xf5,0x8c,0x4c,0x04, 0xd6,0xe5,0xf1,0xba, 0x77,0x9e,0xab,0xfb, 0x5f,0x7b,0xfb,0xd6,
    0x9c,0xfc,0x4e,0x96, 0x7e,0xdb,0x80,0x8d, 0x67,0x9f,0x77,0x7b, 0xc6,0x70,0x2c,0x7d,
    0x39,0xf2,0x33,0x69, 0xa9,0xd9,0xba,0xcf, 0xa5,0x30,0xe2,0x63, 0x04,0x23,0x14,0x61,
    0xb2,0xeb,0x05,0xe2, 0xc3,0x9b,0xe9,0xfc, 0xda,0x6c,0x19,0x07, 0x8c,0x6a,0x9d,0x1b,
};

/* ================ aes ecb 128===================== */
static const unsigned char aes_ecb_128_key_buf[] = {
    0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
};

static const unsigned char aes_ecb_128_encrypt_text[] =
{
    0x3a,0xd7,0x7b,0xb4, 0x0d,0x7a,0x36,0x60, 0xa8,0x9e,0xca,0xf3, 0x24,0x66,0xef,0x97,
    0xf5,0xd3,0xd5,0x85, 0x03,0xb9,0x69,0x9d, 0xe7,0x85,0x89,0x5a, 0x96,0xfd,0xba,0xaf,
    0x43,0xb1,0xcd,0x7f, 0x59,0x8e,0xce,0x23, 0x88,0x1b,0x00,0xe3, 0xed,0x03,0x06,0x88,
    0x7b,0x0c,0x78,0x5e, 0x27,0xe8,0xad,0x3f, 0x82,0x23,0x20,0x71, 0x04,0x72,0x5d,0xd4,
};

/* ================ aes ecb 192===================== */
static const unsigned char aes_ecb_192_key_buf[] = {
    0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
    0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
};

static const unsigned char aes_ecb_192_encrypt_text[] =
{
    0xbd,0x33,0x4f,0x1d, 0x6e,0x45,0xf2,0x5f, 0xf7,0x12,0xa2,0x14, 0x57,0x1f,0xa5,0xcc,
    0x97,0x41,0x04,0x84, 0x6d,0x0a,0xd3,0xad, 0x77,0x34,0xec,0xb3, 0xec,0xee,0x4e,0xef,
    0xef,0x7a,0xfd,0x22, 0x70,0xe2,0xe6,0x0a, 0xdc,0xe0,0xba,0x2f, 0xac,0xe6,0x44,0x4e,
    0x9a,0x4b,0x41,0xba, 0x73,0x8d,0x6c,0x72, 0xfb,0x16,0x69,0x16, 0x03,0xc1,0x8e,0x0e,
};

/* ================ aes ecb 256===================== */
static const unsigned char aes_ecb_256_key_buf[] = {
    0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
    0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
};

static const unsigned char aes_ecb_256_encrypt_text[] =
{
    0xf3,0xee,0xd1,0xbd, 0xb5,0xd2,0xa0,0x3c, 0x06,0x4b,0x5a,0x7e, 0x3d,0xb1,0x81,0xf8,
    0x59,0x1c,0xcb,0x10, 0xd4,0x10,0xed,0x26, 0xdc,0x5b,0xa7,0x4a, 0x31,0x36,0x28,0x70,
    0xb6,0xed,0x21,0xb9, 0x9c,0xa6,0xf4,0xf9, 0xf1,0x53,0xe7,0xb1, 0xbe,0xaf,0xed,0x1d,
    0x23,0x30,0x4b,0x7a, 0x39,0xf9,0xf3,0xff, 0x06,0x7d,0x8d,0x8f, 0x9e,0x24,0xec,0xc7,
};

/* ================ aes ctr 128===================== */
static const unsigned char aes_ctr_128_iv_buf[] = {
    0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
};

static const unsigned char aes_ctr_128_key_buf[] = {
    0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
};

static const unsigned char aes_ctr_128_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
    0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
    0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
    0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
};

static const unsigned char aes_ctr_128_encrypt_text[] =
{
    0x87,0x4d,0x61,0x91, 0xb6,0x20,0xe3,0x26, 0x1b,0xef,0x68,0x64, 0x99,0x0d,0xb6,0xce,
    0x98,0x06,0xf6,0x6b, 0x79,0x70,0xfd,0xff, 0x86,0x17,0x18,0x7b, 0xb9,0xff,0xfd,0xff,
    0x5a,0xe4,0xdf,0x3e, 0xdb,0xd5,0xd3,0x5e, 0x5b,0x4f,0x09,0x02, 0x0d,0xb0,0x3e,0xab,
    0x1e,0x03,0x1d,0xda, 0x2f,0xbe,0x03,0xd1, 0x79,0x21,0x70,0xa0, 0xf3,0x00,0x9c,0xee,
};

/* ================ aes ctr 192===================== */
static const unsigned char aes_ctr_192_iv_buf[] = {
    0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
};

static const unsigned char aes_ctr_192_key_buf[] = {
    0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
    0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
};

static const unsigned char aes_ctr_192_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
    0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
    0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
    0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
};

static const unsigned char aes_ctr_192_encrypt_text[] =
{
    0x1a,0xbc,0x93,0x24, 0x17,0x52,0x1c,0xa2, 0x4f,0x2b,0x04,0x59, 0xfe,0x7e,0x6e,0x0b,
    0x09,0x03,0x39,0xec, 0x0a,0xa6,0xfa,0xef, 0xd5,0xcc,0xc2,0xc6, 0xf4,0xce,0x8e,0x94,
    0x1e,0x36,0xb2,0x6b, 0xd1,0xeb,0xc6,0x70, 0xd1,0xbd,0x1d,0x66, 0x56,0x20,0xab,0xf7,
    0x4f,0x78,0xa7,0xf6, 0xd2,0x98,0x09,0x58, 0x5a,0x97,0xda,0xec, 0x58,0xc6,0xb0,0x50,
};

/* ================ aes ctr 256===================== */
static const unsigned char aes_ctr_256_iv_buf[] = {
    0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
};

static const unsigned char aes_ctr_256_key_buf[] = {
    0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
    0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
};

static const unsigned char aes_ctr_256_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
    0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
    0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
    0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
};

static const unsigned char aes_ctr_256_encrypt_text[] =
{
    0x60,0x1e,0xc3,0x13, 0x77,0x57,0x89,0xa5, 0xb7,0xa7,0xf5,0x04, 0xbb,0xf3,0xd2,0x28,
    0xf4,0x43,0xe3,0xca, 0x4d,0x62,0xb5,0x9a, 0xca,0x84,0xe9,0x90, 0xca,0xca,0xf5,0xc5,
    0x2b,0x09,0x30,0xda, 0xa2,0x3d,0xe9,0x4c, 0xe8,0x70,0x17,0xba, 0x2d,0x84,0x98,0x8d,
    0xdf,0xc9,0xc5,0x8d, 0xb6,0x7a,0xad,0xa6, 0x13,0xc2,0xdd,0x08, 0x45,0x79,0x41,0xa6,
};

/* ================ aes ofb 128===================== */
static const unsigned char aes_ofb_128_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_ofb_128_key_buf[] = {
    0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
};

static const unsigned char aes_ofb_128_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
    0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
    0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
    0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
};

static const unsigned char aes_ofb_128_encrypt_text[] =
{
    0x3b,0x3f,0xd9,0x2e, 0xb7,0x2d,0xad,0x20, 0x33,0x34,0x49,0xf8, 0xe8,0x3c,0xfb,0x4a,
    0x77,0x89,0x50,0x8d, 0x16,0x91,0x8f,0x03, 0xf5,0x3c,0x52,0xda, 0xc5,0x4e,0xd8,0x25,
    0x97,0x40,0x05,0x1e, 0x9c,0x5f,0xec,0xf6, 0x43,0x44,0xf7,0xa8, 0x22,0x60,0xed,0xcc,
    0x30,0x4c,0x65,0x28, 0xf6,0x59,0xc7,0x78, 0x66,0xa5,0x10,0xd9, 0xc1,0xd6,0xae,0x5e,
};

/* ================ aes ofb 192===================== */
static const unsigned char aes_ofb_192_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_ofb_192_key_buf[] = {
    0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
    0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
};

static const unsigned char aes_ofb_192_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
    0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
    0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
    0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
};

static const unsigned char aes_ofb_192_encrypt_text[] =
{
    0xcd,0xc8,0x0d,0x6f, 0xdd,0xf1,0x8c,0xab, 0x34,0xc2,0x59,0x09, 0xc9,0x9a,0x41,0x74,
    0xfc,0xc2,0x8b,0x8d, 0x4c,0x63,0x83,0x7c, 0x09,0xe8,0x17,0x00, 0xc1,0x10,0x04,0x01,
    0x8d,0x9a,0x9a,0xea, 0xc0,0xf6,0x59,0x6f, 0x55,0x9c,0x6d,0x4d, 0xaf,0x59,0xa5,0xf2,
    0x6d,0x9f,0x20,0x08, 0x57,0xca,0x6c,0x3e, 0x9c,0xac,0x52,0x4b, 0xd9,0xac,0xc9,0x2a,
};

/* ================ aes ofb 256===================== */
static const unsigned char aes_ofb_256_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_ofb_256_key_buf[] = {
    0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
    0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
};

static const unsigned char aes_ofb_256_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
    0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
    0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
    0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
};

static const unsigned char aes_ofb_256_encrypt_text[] =
{
    0xdc,0x7e,0x84,0xbf, 0xda,0x79,0x16,0x4b, 0x7e,0xcd,0x84,0x86, 0x98,0x5d,0x38,0x60,
    0x4f,0xeb,0xdc,0x67, 0x40,0xd2,0x0b,0x3a, 0xc8,0x8f,0x6a,0xd8, 0x2a,0x4f,0xb0,0x8d,
    0x71,0xab,0x47,0xa0, 0x86,0xe8,0x6e,0xed, 0xf3,0x9d,0x1c,0x5b, 0xba,0x97,0xc4,0x08,
    0x01,0x26,0x14,0x1d, 0x67,0xf3,0x7b,0xe8, 0x53,0x8f,0x5a,0x8b, 0xe7,0x40,0xe4,0x84,
};

/* ================ aes cfb 128===================== */
static const unsigned char aes_cfb_128_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_cfb_128_key_buf[] = {
    0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
};

static const unsigned char aes_cfb_128_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
};

static const unsigned char aes_cfb_128_encrypt_text[] =
{
    0x3b,0x79,0x42,0x4c, 0x9c,0x0d,0xd4,0x36, 0xba,0xce,0x9e,0x0e, 0xd4,0x58,0x6a,0x4f,
};

/* ================ aes cfb 192===================== */
static const unsigned char aes_cfb_192_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_cfb_192_key_buf[] = {
    0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
    0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
};

static const unsigned char aes_cfb_192_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
};

static const unsigned char aes_cfb_192_encrypt_text[] =
{
    0xcd,0xa2,0x52,0x1e, 0xf0,0xa9,0x05,0xca, 0x44,0xcd,0x05,0x7c, 0xbf,0x0d,0x47,0xa0,
};

/* ================ aes cfb 256===================== */
static const unsigned char aes_cfb_256_iv_buf[] = {
    0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
};

static const unsigned char aes_cfb_256_key_buf[] = {
    0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
    0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
};

static const unsigned char aes_cfb_256_plain_text[] =
{
    0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
};

static const unsigned char aes_cfb_256_encrypt_text[] =
{
    0xdc,0x1f,0x1a,0x85, 0x20,0xa6,0x4d,0xb5, 0x5f,0xcc,0x8a,0xc5, 0x54,0x84,0x4e,0x88,
};

/* ================ des ecb ===================== */
static const unsigned char des_ecb_key_buf[] = {
    0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,
};

static const unsigned char des_ecb_plain_text[] =
{
    0x80,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x40,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
    0x20,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x10,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x04,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
    0x02,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
};

static const unsigned char des_ecb_encrypt_text[] =
{
    0x95,0xF8,0xA5,0xE5, 0xDD,0x31,0xD9,0x00, 0xDD,0x7F,0x12,0x1C, 0xA5,0x01,0x56,0x19,
    0x2E,0x86,0x53,0x10, 0x4F,0x38,0x34,0xEA, 0x4B,0xD3,0x88,0xFF, 0x6C,0xD8,0x1D,0x4F,
    0x20,0xB9,0xE7,0x67, 0xB2,0xFB,0x14,0x56, 0x55,0x57,0x93,0x80, 0xD7,0x71,0x38,0xEF,
    0x6C,0xC5,0xDE,0xFA, 0xAF,0x04,0x51,0x2F, 0x0D,0x9F,0x27,0x9B, 0xA5,0xD8,0x72,0x60,
};

/* ================ des cbc ===================== */
static const unsigned char des_cbc_key_buf[] = {
    0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef,
};

static const unsigned char des_cbc_iv_buf[] = {
    0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
};

static const unsigned char des_cbc_plain_text[] =
{
    0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x68,0x65,0x20,0x74, 0x69,0x6d,0x65,0x20,
    0x66,0x6f,0x72,0x20, 0x61,0x6c,0x6c,0x20,

};

static const unsigned char des_cbc_encrypt_text[] =
{
    0xe5,0xc7,0xcd,0xde, 0x87,0x2b,0xf2,0x7c, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
    0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
};

/* ================ des ofb ===================== */
static const unsigned char des_ofb_key_buf[] = {
    0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef,
};

static const unsigned char des_ofb_iv_buf[] = {
    0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
};

static const unsigned char des_ofb_plain_text[] =
{
    0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
    0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
};

static const unsigned char des_ofb_encrypt_text[] =
{
    0xf3,0x09,0x62,0x49, 0xc7,0xf4,0x6e,0x51, 0x1e,0x7e,0x5e,0x50, 0xcb,0xbe,0xc4,0x10,
    0x33,0x35,0xa1,0x8a, 0xde,0x4a,0x91,0x15,
};

/* ================ des cfb ===================== */
static const unsigned char des_cfb_key_buf[] = {
    0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef,
};

static const unsigned char des_cfb_iv_buf[] = {
    0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
};

static const unsigned char des_cfb_plain_text[] =
{
    0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
    0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6,
};

static const unsigned char des_cfb_encrypt_text[] =
{
    0xf3,0x1f,0xda,0x07,0x01,0x14,0x62,0xee,0x33,0x79,0xda,0x67,0xd6,0xd8,0x94,0x3b,
    0x71,0xde,0xe2,0xf3,0x50,0x80,0xd6,0x2b,
};

/* ================ des3 ecb ===================== */
static const unsigned char des3_ecb_key_buf[] = {
    0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
    0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
};

static const unsigned char des3_ecb_plain_text[] =
{
    0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
    0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
};

static const unsigned char des3_ecb_encrypt_text[] =
{
    0x31,0x4f,0x83,0x27, 0xfa,0x7a,0x09,0xa8, 0xd5,0x89,0x5f,0xad, 0xe9,0x8f,0xae,0xdf,
    0x98,0xf4,0x70,0xeb, 0x35,0x53,0xa5,0xda,
};

/* ================ des3 cbc ===================== */
static const unsigned char des3_cbc_key_buf[] =
{
    0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
    0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
};

static const unsigned char des3_cbc_iv_buf[] =
{
    0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
};

static const unsigned char des3_cbc_plain_text[] =
{
    0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
    0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
};

static const unsigned char des3_cbc_encrypt_text[] =
{
    0xf3,0xc0,0xff,0x02, 0x6c,0x02,0x30,0x89, 0xc4,0x3a,0xdd,0x8f, 0xd8,0xcd,0x5e,0x43,
    0x2b,0xfd,0x41,0xd3, 0x13,0x0b,0xcf,0x40,
};

/* ================ des3 ofb ===================== */
static const unsigned char des3_ofb_key_buf[] =
{
    0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
    0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
};

static const unsigned char des3_ofb_iv_buf[] =
{
    0x23,0x45,0x67,0x89 ,0x0a,0xbc,0xde,0x0f,
};

static const unsigned char des3_ofb_plain_text[] =
{
    0xe6,0xf7,0x72,0x06, 0x97,0x32,0x07,0x04, 0x3e,0x93,0x40,0x08, 0xc3,0x89,0xc0,0x0f,
    0x83,0x78,0x84,0x99, 0xa7,0xc0,0x5f,0x06,
};

static const unsigned char des3_ofb_encrypt_text[] =
{
    0xf3,0x24,0x21,0x7f, 0xf3,0x55,0x3c,0x3b, 0xe7,0x46,0x2d,0x4a, 0xe5,0xed,0x98,0x27,
    0x05,0x17,0x55,0x81, 0xf8,0x62,0x5b,0xa6,
};

/* ================ des3 cfb ===================== */
static const unsigned char des3_cfb_key_buf[] =
{
    0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
    0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
};

static const unsigned char des3_cfb_iv_buf[] =
{
    0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
};

static const unsigned char des3_cfb_plain_text[] =
{
    0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
    0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
};

static const unsigned char des3_cfb_encrypt_text[] =
{
    0xee,0x9b,0x04,0xff, 0xca,0xce,0xc8,0x06, 0x5b,0xcc,0x4f,0x67, 0x8f,0x00,0xd7,0x14,
    0x4d,0xf6,0x74,0xfc, 0xd6,0x98,0x9f,0x8f,
};

int runtest(struct crypt_method *method)
{
    struct crypt_cipher *cipher;
    unsigned char *in, *out, *tmp;
    long page_size;

    /*just for dubug..printf the result of encrypt*/
    /*
    int i = 0;
    unsigned char result[64];
    int *p = result;
    */
    /*end*/

    int ret = 0;

    page_size = sysconf(_SC_PAGESIZE);
    tmp = malloc(method->text_len + page_size);
    if (tmp == NULL) {
        printf("error: malloc buffer failed.\n");
        return -1;
    }
    in = (unsigned char *)( ((long)tmp + page_size - 1) & ~(page_size - 1) );

    tmp = malloc(method->text_len + page_size);
    if (tmp == NULL) {
        printf("error: malloc buffer failed.\n");
        return -1;
    }
    out = (unsigned char *)( ((long)tmp + page_size - 1) & ~(page_size - 1) );

    ret = crypt_cipher_init(&cipher, method->type, method->mode, method->key_buf, method->key_len);
    if (0 != ret) {
        printf("error: crypt_cipher_init failed, ret=%d\n", ret);
        return ret;
    }

    memcpy(in, method->plain_buf, method->text_len);
    memset(out, 0, method->text_len);
    ret = crypt_cipher_encrypt(cipher, (const char *)in, (char *)out, method->text_len, (const char *)method->iv_buf, method->iv_len);
    if (0 != ret) {
        printf("error: crypt_cipher_encrypt failed, ret=%d\n", ret);
        goto exit;
    }

    /*debug...printf the result of encrypt*/
    /*
    memcpy(p, out, method->text_len);
    for (i = 0; i < 24; i++) {
        printf("times: %d, Ciphertest: %x\n", i, result[i]);
        printf("\n");
    }
    */

    ///*
    if (0 != memcmp(method->encrypt_buf, out, method->text_len))
        printf("FAIL -> %s(%s) Encrypt test\n", method->mode, method->type);
    else
        printf("PASS -> %s(%s) Encrypt test\n", method->mode, method->type);

    memcpy(in, method->encrypt_buf, method->text_len);
    memset(out, 0, method->text_len);
    ret = crypt_cipher_decrypt(cipher, (const char *)in, (char *)out, method->text_len, (const char *)method->iv_buf, method->iv_len);
    if (0 != ret) {
        printf("error: crypt_cipher_decrypt failed, ret=%d\n", ret);
        goto exit;
    }
    if (0 != memcmp((unsigned char*)method->plain_buf, out, method->text_len))
        printf("FAIL -> %s(%s) Decrypt test\n", method->mode, method->type);
    else
        printf("PASS -> %s(%s) Decrypt test\n", method->mode, method->type);
    //*/
exit:
    crypt_cipher_destroy(cipher);
    return ret;
}

int main(int argc, char const *argv[])
{
    struct crypt_method aes_cbc_128 = {
        .type = "aes",
        .mode = "cbc",
        .plain_buf = (char *)plain_text,
        .encrypt_buf = (char *)aes_cbc_128_encrypt_text,
        .key_buf = (char *)aes_cbc_128_key_buf,
        .key_len = 16,
        .iv_buf = (char *)aes_cbc_128_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_cbc_192 = {
        .type = "aes",
        .mode = "cbc",
        .plain_buf = (char *)plain_text,
        .encrypt_buf = (char *)aes_cbc_192_encrypt_text,
        .key_buf = (char *)aes_cbc_192_key_buf,
        .key_len = 24,
        .iv_buf = (char *)aes_cbc_192_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_cbc_256 = {
        .type = "aes",
        .mode = "cbc",
        .plain_buf = (char *)plain_text,
        .encrypt_buf = (char *)aes_cbc_256_encrypt_text,
        .key_buf = (char *)aes_cbc_256_key_buf,
        .key_len = 32,
        .iv_buf = (char *)aes_cbc_256_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_ecb_128 = {
        .type = "aes",
        .mode = "ecb",
        .plain_buf = (char *)plain_text,
        .encrypt_buf = (char *)aes_ecb_128_encrypt_text,
        .key_buf = (char *)aes_ecb_128_key_buf,
        .key_len = 16,
        .iv_buf = NULL,
        .iv_len = 0,
        .text_len = 64
    };

    struct crypt_method aes_ecb_192 = {
        .type = "aes",
        .mode = "ecb",
        .plain_buf = (char *)plain_text,
        .encrypt_buf = (char *)aes_ecb_192_encrypt_text,
        .key_buf = (char *)aes_ecb_192_key_buf,
        .key_len = 24,
        .iv_buf = NULL,
        .iv_len = 0,
        .text_len = 64
    };

    struct crypt_method aes_ecb_256 = {
        .type = "aes",
        .mode = "ecb",
        .plain_buf = (char *)plain_text,
        .encrypt_buf = (char *)aes_ecb_256_encrypt_text,
        .key_buf = (char *)aes_ecb_256_key_buf,
        .key_len = 32,
        .iv_buf = NULL,
        .iv_len = 0,
        .text_len = 64
    };

    struct crypt_method aes_ctr_128 = {
        .type = "aes",
        .mode = "ctr",
        .plain_buf = (char *)aes_ctr_128_plain_text,
        .encrypt_buf = (char *)aes_ctr_128_encrypt_text,
        .key_buf = (char *)aes_ctr_128_key_buf,
        .key_len = 16,
        .iv_buf = (char *)aes_ctr_128_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_ctr_192 = {
        .type = "aes",
        .mode = "ctr",
        .plain_buf = (char *)aes_ctr_192_plain_text,
        .encrypt_buf = (char *)aes_ctr_192_encrypt_text,
        .key_buf = (char *)aes_ctr_192_key_buf,
        .key_len = 24,
        .iv_buf = (char *)aes_ctr_192_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_ctr_256 = {
        .type = "aes",
        .mode = "ctr",
        .plain_buf = (char *)aes_ctr_256_plain_text,
        .encrypt_buf = (char *)aes_ctr_256_encrypt_text,
        .key_buf = (char *)aes_ctr_256_key_buf,
        .key_len = 32,
        .iv_buf = (char *)aes_ctr_256_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_ofb_128 = {
        .type = "aes",
        .mode = "ofb",
        .plain_buf = (char *)aes_ofb_128_plain_text,
        .encrypt_buf = (char *)aes_ofb_128_encrypt_text,
        .key_buf = (char *)aes_ofb_128_key_buf,
        .key_len = 16,
        .iv_buf = (char *)aes_ofb_128_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_ofb_192 = {
        .type = "aes",
        .mode = "ofb",
        .plain_buf = (char *)aes_ofb_192_plain_text,
        .encrypt_buf = (char *)aes_ofb_192_encrypt_text,
        .key_buf = (char *)aes_ofb_192_key_buf,
        .key_len = 24,
        .iv_buf = (char *)aes_ofb_192_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_ofb_256 = {
        .type = "aes",
        .mode = "ofb",
        .plain_buf = (char *)aes_ofb_256_plain_text,
        .encrypt_buf = (char *)aes_ofb_256_encrypt_text,
        .key_buf = (char *)aes_ofb_256_key_buf,
        .key_len = 32,
        .iv_buf = (char *)aes_ofb_256_iv_buf,
        .iv_len = 16,
        .text_len = 64
    };

    struct crypt_method aes_cfb_128 = {
        .type = "aes",
        .mode = "cfb",
        .plain_buf = (char *)aes_cfb_128_plain_text,
        .encrypt_buf = (char *)aes_cfb_128_encrypt_text,
        .key_buf = (char *)aes_cfb_128_key_buf,
        .key_len = 16,
        .iv_buf = (char *)aes_cfb_128_iv_buf,
        .iv_len = 16,
        .text_len = 16
    };

    struct crypt_method aes_cfb_192 = {
        .type = "aes",
        .mode = "cfb",
        .plain_buf = (char *)aes_cfb_192_plain_text,
        .encrypt_buf = (char *)aes_cfb_192_encrypt_text,
        .key_buf = (char *)aes_cfb_192_key_buf,
        .key_len = 24,
        .iv_buf = (char *)aes_cfb_192_iv_buf,
        .iv_len = 16,
        .text_len = 16
    };

    struct crypt_method aes_cfb_256 = {
        .type = "aes",
        .mode = "cfb",
        .plain_buf = (char *)aes_cfb_256_plain_text,
        .encrypt_buf = (char *)aes_cfb_256_encrypt_text,
        .key_buf = (char *)aes_cfb_256_key_buf,
        .key_len = 32,
        .iv_buf = (char *)aes_cfb_256_iv_buf,
        .iv_len = 16,
        .text_len = 16
    };

    struct crypt_method des_ecb = {
        .type = "des",
        .mode = "ecb",
        .plain_buf = (char *)des_ecb_plain_text,
        .encrypt_buf = (char *)des_ecb_encrypt_text,
        .key_buf = (char *)des_ecb_key_buf,
        .key_len = 8,
        .iv_buf = NULL,
        .iv_len = 0,
        .text_len = 64
    };

    struct crypt_method des_cbc = {
        .type = "des",
        .mode = "cbc",
        .plain_buf = (char *)des_cbc_plain_text,
        .encrypt_buf = (char *)des_cbc_encrypt_text,
        .key_buf = (char *)des_cbc_key_buf,
        .key_len = 8,
        .iv_buf = (char *)des_cbc_iv_buf,
        .iv_len = 8,
        .text_len = 24
    };

    struct crypt_method des_ofb = {
        .type = "des",
        .mode = "ofb",
        .plain_buf = (char *)des_ofb_plain_text,
        .encrypt_buf = (char *)des_ofb_encrypt_text,
        .key_buf = (char *)des_ofb_key_buf,
        .key_len = 8,
        .iv_buf = (char *)des_ofb_iv_buf,
        .iv_len = 8,
        .text_len = 24
    };

    struct crypt_method des_cfb = {
        .type = "des",
        .mode = "cfb",
        .plain_buf = (char *)des_cfb_plain_text,
        .encrypt_buf = (char *)des_cfb_encrypt_text,
        .key_buf = (char *)des_cfb_key_buf,
        .key_len = 8,
        .iv_buf = (char *)des_cfb_iv_buf,
        .iv_len = 8,
        .text_len = 24
    };

    struct crypt_method des3_ecb = {
        .type = "des3",
        .mode = "ecb",
        .plain_buf = (char *)des3_ecb_plain_text,
        .encrypt_buf = (char *)des3_ecb_encrypt_text,
        .key_buf = (char *)des3_ecb_key_buf,
        .key_len = 24,
        .iv_buf = NULL,
        .iv_len = 0,
        .text_len = 24
    };

    struct crypt_method des3_cbc = {
        .type = "des3",
        .mode = "cbc",
        .plain_buf = (char *)des3_cbc_plain_text,
        .encrypt_buf = (char *)des3_cbc_encrypt_text,
        .key_buf = (char *)des3_cbc_key_buf,
        .key_len = 24,
        .iv_buf = (char *)des3_cbc_iv_buf,
        .iv_len = 8,
        .text_len = 24
    };

    struct crypt_method des3_ofb = {
        .type = "des3",
        .mode = "ofb",
        .plain_buf = (char *)des3_ofb_plain_text,
        .encrypt_buf = (char *)des3_ofb_encrypt_text,
        .key_buf = (char *)des3_ofb_key_buf,
        .key_len = 24,
        .iv_buf = (char *)des3_ofb_iv_buf,
        .iv_len = 8,
        .text_len = 24
    };

    struct crypt_method des3_cfb = {
        .type = "des3",
        .mode = "cfb",
        .plain_buf = (char *)des3_cfb_plain_text,
        .encrypt_buf = (char *)des3_cfb_encrypt_text,
        .key_buf = (char *)des3_cfb_key_buf,
        .key_len = 24,
        .iv_buf = (char *)des3_cfb_iv_buf,
        .iv_len = 8,
        .text_len = 24
    };

    runtest(&aes_cbc_128);
    runtest(&aes_cbc_192);
    runtest(&aes_cbc_256);
    runtest(&aes_ecb_128);
    runtest(&aes_ecb_192);
    runtest(&aes_ecb_256);
    runtest(&aes_ctr_128);
    runtest(&aes_ctr_192);
    runtest(&aes_ctr_256);
    runtest(&aes_ofb_128);
    runtest(&aes_ofb_192);
    runtest(&aes_ofb_256);
    runtest(&aes_cfb_128);
    runtest(&aes_cfb_192);
    runtest(&aes_cfb_256);
    runtest(&des_ecb);
    runtest(&des_cbc);
    runtest(&des_ofb);
    runtest(&des_cfb);
    runtest(&des3_ecb);
    runtest(&des3_cbc);
    runtest(&des3_ofb);
    runtest(&des3_cfb);

    return 0;
}